/*
 * tabmix.js
 *
 * original code by Hemiola SUN, further developed by onemen and CPU
 */
var gPref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
var gIsOldBrowser = typeof(Components.interfaces.nsIXULAppInfo) == "undefined";
var gIsFirefox2 = typeof(BrowserOpenAddonsMgr) == "function";
var gIsPlaces = typeof(PlacesController) == "object";

function TM_init()
{
  //add a splitter
  gBrowser.mSplitter = document.createElement("splitter");
  gBrowser.mSplitter.className = "chromeclass-extrachrome tabtreesplitter";
  gBrowser.mSplitter.orient = "horizontal";
  gBrowser.mStrip.parentNode.
    insertBefore(gBrowser.mSplitter, gBrowser.mStrip.nextSibling);


  //add a vertical indicator
  gBrowser.mVerticalTabDropIndicatorBar = document.createElement("xul::vbox");
  gBrowser.mVerticalTabDropIndicatorBar.className = "vertical-tab-drop-indicator-bar";
  gBrowser.mVerticalTabDropIndicatorBar.orient = "vertical";
  var box = document.createElement("xul::vbox");
  box.className = "vertical-tab-drop-indicator";
  gBrowser.mVerticalTabDropIndicatorBar.appendChild(box);
  gBrowser.mStrip.parentNode.insertBefore(gBrowser.mVerticalTabDropIndicatorBar, 
                                          gBrowser.mSplitter);



  var historyMenu = document.getElementById("goPopup").parentNode;
  if (gIsPlaces) {
     TMP_Places.init();
    // history menu open in new tab if the curren tab is locked
    if (historyMenu)
      historyMenu.setAttribute("oncommand", "TMP_Places.historyMenu(event);");
  }
  else {
    Click2TabLoadBookmark.init();
    if (historyMenu)
      historyMenu.setAttribute("oncommand", "var url = event.target.getAttribute('statustext'); if (url) {openUILinkIn(url, whereToOpenLinkTabmix(event, prefStringTMHistory)); content.focus();}");
  }

  // disable the "Open New Window action in Single Window Mode...
  var cmdNewWindow = document.getElementById("cmd_newNavigator");
  var originalNewNavigator = cmdNewWindow.getAttribute("oncommand");
  cmdNewWindow.setAttribute("oncommand","if (gSingleWindowMode) BrowserOpenTab(); else {" + originalNewNavigator + "}");

  // replace browser handlers with ours so it recognizes when tabs are acted on
  gBrowser.onTabBarDblClick = TM_onTabBarDblClick;
  gBrowser.onTabClick = TM_checkClick;
  if (gIsOldBrowser)
    gBrowser.updateContextTab = TMupdateContextTab;

  gBrowser.mTabBox.insertBefore(document.getElementById('vide-bar'), gBrowser.mTabBox.firstChild);

  gBrowser.closedTabs = [];

  document.getElementById("content").onresize = tabBarWidthChange;
  document.getElementById("contentAreaContextMenu").addEventListener("popupshowing", TM_checkContentMenu, false);
  document.getElementById("contentAreaContextMenu").addEventListener("popuphiding", TM_onCloseContextMenu, false);

  var tabContextMenu = gBrowser.mStrip.firstChild.nextSibling;
  tabContextMenu.setAttribute("onpopuphidden", tabContextMenu.getAttribute("onpopuphidden") + "if (event.target == this) TM_hidePopup();");
  tabContextMenu.addEventListener("popupshowing", Tm_checkTabClick, false);
  tabContextMenu.addEventListener("popupshown", TMP_tabContextMenuShown, false);

  // override some of All-in-One Gestures function
  // override the duplicate tab function
  if (typeof aioDupTab == 'function')
    aioDupTab = function() { gBrowser.duplicateTab(gBrowser.mCurrentTab); };

  //override the duplicate in new window function
  if (typeof aioDupWindow == 'function')
    aioDupWindow = function() { gBrowser.duplicateInWindow(gBrowser.mCurrentTab); };

  //override the aioCloseWindow function
  if (typeof aioCloseWindow == 'function')
    aioCloseWindow = BrowserTryToCloseWindow;

  // for session manager
  window.setTimeout( function () {
                       SessionManager.init();
                       gBrowser.mTabContainer.nextTab = 1;
                       if (gIsFirefox2)
                         getClosedTabs(); // XXX temp -- get closed-tabs from nsSessionStore
                       var aTab = gBrowser.mTabContainer.firstChild;
                       if (aTab != gBrowser.mCurrentTab) {
                          aTab.removeAttribute("selected");
                          aTab.removeAttribute("flst_id");
                       };
                     }, 0 );

  //Browser:Home open in new tab if the curren tab is locked
  window.BrowserHome = TM_BrowserHome;

  // add tooltip to close tab button on tab for firefox 1.5 +
  if (typeof(Components.interfaces.nsIXULAppInfo) != "undefined")
    gBrowser.mStrip.firstChild.setAttribute("onpopupshowing","return this.parentNode.parentNode.parentNode.TMP_createTooltip(event);");

  //fix Typo: extensions.tabmix.cloesedWinToolsMenu should be extensions.tabmix.closedWinToolsMenu.
  //version tabmix 0.3 befor 2005-11-28
  var oldPref = "extensions.tabmix.cloesedWinToolsMenu";
  var newPref = "extensions.tabmix.closedWinToolsMenu";
  if (gPref.prefHasUserValue(oldPref)) {
    gPref.setBoolPref(newPref, false); // default is true
    gPref.clearUserPref(oldPref)
  }

  // fix FeedHandler to open new tab if tab is lock (FF 2.0 +)
  var feedButton = document.getElementById("feed-button");
  if (gIsFirefox2 && feedButton)
    feedButton.firstChild.setAttribute("oncommand", "gBrowser.TMP_openURI(event.target.getAttribute('feed'));");

  // add call to TMP_Sanitizer
  // nsBrowserGlue.js use loadSubScript to load Sanitizer so we need to add this here
  var cmd = document.getElementById('Tools:Sanitize');
  if (cmd) {
    cmd.setAttribute('oncommand', cmd.getAttribute('oncommand') + ' TMP_Sanitizer.tryToSanitize();');
  }

}

function TM_deinit ()
{
  if (!gBrowser.mStrip.hasAttribute("ondraggesture")) {
    gBrowser.mStrip.removeEventListener("draggesture", TMP_TabDragGesture, true);
    gBrowser.mStrip.removeEventListener("dragover", TMP_TabDragOver, true);
    gBrowser.mStrip.removeEventListener("dragdrop", TMP_TabDragDrop, true);
    gBrowser.mStrip.removeEventListener("dragexit", TMP_TabDragExit, true);
  }
  if ("mTabDropIndicatorBar" in gBrowser) {
    gBrowser.mTabDropIndicatorBar.removeEventListener('dragover', TMP_TabDragOver, true);
    gBrowser.mTabDropIndicatorBar.removeEventListener('dragdrop', TMP_TabDragDrop, true);
  }

  if (!gIsPlaces)
    Click2TabLoadBookmark.deinit();

  SessionManager.deinit(numberOfWindows() == 0, false);

  document.getElementById("contentAreaContextMenu").removeEventListener("popupshowing", TM_checkContentMenu, false);
  document.getElementById("contentAreaContextMenu").removeEventListener("popuphiding", TM_onCloseContextMenu, false);
  var tabContextMenu = gBrowser.mStrip.firstChild.nextSibling;
  tabContextMenu.removeEventListener("popupshowing", Tm_checkTabClick, false);
  tabContextMenu.removeEventListener("popupshown", TMP_tabContextMenuShown, false);

  TMP_LastTab.deinit();
  tabxOnClose();
  TMP_TBP_exit();
  tabxPrefObserver.removeObserver();
  window.removeEventListener("unload", TM_deinit, false);

}

// Create new items in the context menu of tab bar
var newMenuItems = ["tm-duplicateTab","tm-duplicateinWin","tm-detachTab","tm-mergeWindowsTab","tm-renameTab",
                    "tm-copyTabUrl", "tm-autoreloadTab_menu", "tm-reloadOther","tm-reloadLeft","tm-reloadRight","tm-separator",
                    "tm-undoCloseTab","tm-undoCloseList","tm-separator-2",
                    "tm-closeAllTabs","tm-closeSimilar","tm-closeLeftTabs","tm-closeRightTabs",
                    "tm-docShell","tm-freezeTab","tm-protectTab","tm-lockTab"];


var newMenuOrders = [ 1, 2, 3, 4, 5, 6,
                      9, 11, 12, 13, 14,
                      15, 16, 17,
                      19, 20, 22, 23,
                      25, 26, 27, 28];

function TM_creatMenuItems () {
  var tabContextMenu = window.getBrowser().mStrip.firstChild.nextSibling;

  tabContextMenu.setAttribute("id", "menuedit-tabContextMenu");
  var menuItems = tabContextMenu.childNodes;

  var i, separator = 0;
  for ( i = 0; i < menuItems.length; i++ ) {
      if (menuItems[i].hasAttribute("id"))
         continue;

      else if (menuItems[i].localName == "menuseparator")
         menuItems[i].setAttribute("id", "original-separator-" + separator++);

      else if (menuItems[i].hasAttribute("xbl:inherits")) {
         if (menuItems[i].getAttribute("xbl:inherits") == "oncommand=onnewtab") {
            menuItems[i].setAttribute("id", "tm-newtab");
//            menuItems[i].setAttribute("oncommand", "var tabbrowser = this.parentNode.parentNode.parentNode.parentNode; TMP_BrowserOpenTab(tabbrowser.mContextTab);");
            menuItems[i].setAttribute("oncommand", "TMP_BrowserOpenTab();");
            menuItems[i].setAttribute("_newtab", menuItems[i].getAttribute("label"));
            menuItems[i].setAttribute("_afterthis", document.getElementById("tm-separator").getAttribute("_afterthis"));
            menuItems[i].removeAttribute("xbl:inherits");
         }
      }

      else {
         var aCommand = menuItems[i].getAttribute("oncommand");
         if (aCommand.indexOf("reloadTab") != -1 ) menuItems[i].setAttribute("id", "tm-reloadTab");
         else if (aCommand.indexOf("reloadAllTabs") != -1 ) menuItems[i].setAttribute("id", "tm-reloadAllTabs");
         else if (aCommand.indexOf("removeAllTabsBut") != -1 ) menuItems[i].setAttribute("id", "tm-removeAllTabsBut");
         else if (aCommand.indexOf("removeTab") != -1 ) menuItems[i].setAttribute("id", "tm-removeTab");
         else if (aCommand.indexOf("BookmarkThisTab") != -1 ) menuItems[i].setAttribute("id", "tm-addBookmarkAs");
         else if (menuItems[i].hasAttribute("command"))
               if (menuItems[i].getAttribute("command") == "Browser:BookmarkAllTabs") menuItems[i].setAttribute("id", "tm-bookmarkAllTabs");
      }
  }
  // group the close-tab options together
  var closeTab = document.getElementById("tm-removeTab");
  var closeOther = document.getElementById("tm-removeAllTabsBut");
  tabContextMenu.insertBefore( closeTab, closeOther );

  // insert new menuitems and separators
  for ( i = 0; i < newMenuItems.length; i++ ) {
    var newMenuItem = document.getElementById(newMenuItems[i]);
    var item;
    if (tabContextMenu.childNodes.length < newMenuOrders[i]+1) item = null;
    else item = tabContextMenu.childNodes[newMenuOrders[i]];
    tabContextMenu.insertBefore( newMenuItem, item);
  }

  // restore original-separator-2 to its original position
  var origSep2 = document.getElementById("original-separator-2");
  var addBookmark = document.getElementById("tm-addBookmarkAs");
  if (origSep2 && addBookmark)
    tabContextMenu.insertBefore(origSep2, addBookmark);

  // insret IE Tab menu-items befor Bookmakrs menu-items or at the end if origSep2 is null
  if (window.gIeTab) {
    var aFunction = "createTabbarMenu" in IeTab.prototype ? "createTabbarMenu" : "init";
    eval("IeTab.prototype." + aFunction +" ="+IeTab.prototype[aFunction].toString().replace(
         'tabbarMenu.insertBefore(document.getElementById("ietab-tabbar-sep"), separator);',
         'separator = document.getElementById("original-separator-2"); $&'
    ));
  }
}

function TMP_openDialog(panel)
{
  var WindowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
                        .getService(Components.interfaces.nsIWindowMediator);
  var tabmixOptionsWin = WindowManager.getMostRecentWindow("mozilla:tabmixopt");
  if (tabmixOptionsWin) {

    var appearanceWin = WindowManager.getMostRecentWindow("mozilla:tabmixopt-appearance");
    var filetypeWin = WindowManager.getMostRecentWindow("mozilla:tabmixopt-filetype");

    if (!appearanceWin && !filetypeWin && panel > -1)
      tabmixOptionsWin.TM_selectTab(panel);

    var incompatibleBox = tabmixOptionsWin.document.getElementById("incompatible");
    var incompatibleStatus = incompatibleBox.collapsed;

    incompatibleBox.collapsed = getExtensions().length == 0;
    if (incompatibleStatus != incompatibleBox.collapsed)
      tabmixOptionsWin.sizeToContent();

    (appearanceWin || filetypeWin || tabmixOptionsWin).focus();
  }
  else {
    if(panel > -1)
      gPref.setIntPref('extensions.tabmix.selected_tab', panel);

    window.openDialog("chrome://tabtreemix/content/pref/pref-tabmix.xul", "Tab Tree Mix", "chrome,titlebar,toolbar,close,dialog=no");
  }
}

/*
   functions to disable incompatible extensions
   original code by mrtech local_install.js , code modified by onemen 2006-01-13
*/
function disableExtensions(aWindow) {
   var warning_list = getExtensions();

   if (warning_list.length == 0) {
      return true;
   }

   try {
      warning_list.sort();
   } catch(ex) { }

   var outStr = "";
   for (var w in warning_list) {
      outStr += " - " + warning_list[w]._name + " " + warning_list[w]._version + "\n";
   }

   var defaultButton = gIsOldBrowser ? BUTTON_OK : BUTTON_EXTRA1;
   var showatStart = gPref.getBoolPref("extensions.tabmix.disableIncompatible")
   var chkBoxState = showatStart ? CHECKBOX_CHECKED : CHECKBOX_UNCHECKED;

   var bundleID = "tmp-string-bundle"
   var _stingBundle = document.getElementById(bundleID);
   var title = _stingBundle.getString("incompatible.title");
   var msg = _stingBundle.getString("incompatible.msg0") + "\n"
           + _stingBundle.getString("incompatible.msg1") + "\n\n" + outStr + "\n\n";
   var chkBoxLabel = _stingBundle.getString("incompatible.chkbox.label");
   var buttons = [SessionManager.setLabel("incompatible.button0", bundleID),
                 SessionManager.setLabel("incompatible.button1", bundleID)];
   if (!gIsOldBrowser)
      buttons.push(SessionManager.setLabel("incompatible.button2", bundleID));

   var result = TM_PromptService([defaultButton, HIDE_MENUANDTEXT, chkBoxState],[title, msg, "", chkBoxLabel, buttons.join("\n")], aWindow);
   if (result.checked != showatStart) {
      gPref.setBoolPref("extensions.tabmix.disableIncompatible", result.checked);
      nsIPrefServiceObj.savePrefFile(null); // store the pref immediately
   }

   if (result.button != BUTTON_CANCEL) {
      var extensionManager = Components.classes["@mozilla.org/extensions/manager;1"]
                             .getService(Components.interfaces.nsIExtensionManager);
      var _Function = gIsOldBrowser ? "disableExtension" : "disableItem";
      for (w in warning_list) {
         try{
            extensionManager[_Function](warning_list[w]._guid);
         } catch(e) {
            tmLog("error while disabled " + warning_list[w]._name)
         }
      }

      var dataSource = extensionManager.datasource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
      if (dataSource)
         dataSource.Flush();

      if (!gIsOldBrowser && result.button == BUTTON_EXTRA1 && canQuitApplication()) {
         var appStartup = Components.interfaces.nsIAppStartup;
         Components.classes["@mozilla.org/toolkit/app-startup;1"]
            .getService(appStartup).quit(appStartup.eRestart | appStartup.eAttemptQuit);
      }
      else {
         msg = _stingBundle.getString("incompatible.msg2");
         buttons = ["", SessionManager.setLabel("sm.button.continue")].join("\n");
         TM_PromptService([BUTTON_CANCEL, HIDE_MENUANDTEXT, HIDE_CHECKBOX],[title, msg, "", "", buttons], aWindow);
      }

      return true;
   }
   return false;
}

function getExtensions() {

   var guid_list = {};
   /*
       The following extensions are integrated or incompatible with Tab Tree Mix

       add extensions ID in lowercase.
   */
   guid_list['{00bdd586-51fb-4b06-9c23-af2fb7609bf3}'] = true;    //   Basics
   guid_list['{b98719b3-76d6-4bec-aeed-3ab542b23bd7}'] = true;    //   BlankLast
   guid_list['{47921160-3085-4023-a145-8ec466babfba}'] = true;    //   Click2Tab
   guid_list['{b0f9cad2-ebae-4685-b518-d3d9b41ea183}'] = true;    //   Close Tab On Double Click
   guid_list['ctc@clav.mozdev.org'] = true;                       //   CTC
   guid_list['{61ed2a9a-39eb-4aaf-bd14-06dfbe8880c3}'] = true;    //   Duplicate Tab
   guid_list['flowtabs'] = true;                                  //   Flowing Tabs
   guid_list['{cd2b821e-19f9-40a7-ac5c-08d6c197fc43}'] = true;    //   FLST
   guid_list['{68e5dd30-a659-4987-99f9-eaf21f9d4140}'] = true;    //   LastTab
   guid_list['minit@dorando'] = true;                             //   MiniT
   guid_list['minit-drag'] = true;                                //   miniT-drag
   guid_list['minit-tabscroll@dorando'] = true;                   //   miniT-tabscroll
   guid_list['new-tab-button-on-tab-bar@mikegoodspeed.com'] = true;   //   new tab button on tab bar
   guid_list['{66E978CD-981F-47DF-AC42-E3CF417C1467}'] = true;    //   new tab homepage
   guid_list['newtaburl@sogame.cat'] = true;                      //   NewTabURL
   guid_list['{4b2867d9-2973-42f3-bd9b-5ad30127c444}'] = true;    //   Petite Tabbrowser Extensions
   guid_list['{888d99e7-e8b5-46a3-851e-1ec45da1e644}'] = true;    //   ReloadEvery
   guid_list['{aede9b05-c23c-479b-a90e-9146ed62d377}'] = true;    //   Reload Tab On Double-Click
   guid_list['{492aa940-beaa-11d8-9669-0800200c9a66}'] = true;    //   Scrollable Tabs
   guid_list['{eb922232-fd76-4eb0-bd5a-c1cba4238343}'] = true;    //   Single Window
   guid_list['{149C6CC6-EC62-4ebd-B719-3C2E867930C7}'] = true;    //   Stack style tabs
   guid_list['supert@studio17.wordpress.com'] = true;             //   superT
   guid_list['tabbin'] = true;                                    //   Tab Bin
   guid_list['{43520b8f-4107-4351-ac64-9bcc5eea24b9}'] = true;    //   Tab Clicking Options
   guid_list['{bea6d1a7-882d-425f-bc75-944e0063ff3b}'] = true;    //   Tab Mix [original one]
   guid_list['tabtowindow@sogame.cat'] = true;                    //   Tab to window
   guid_list['tabx@clav.mozdev.org'] = true;                      //   Tab X
   guid_list['{0b0b0da8-08ba-4bc6-987c-6bc9f4d8a81e}'] = true;    //   Tabbrowser Extensions
   guid_list['{9b9d2aaa-ae26-4447-a7a1-633a32b19ddd}'] = true;    //   Tabbrowser Preferences
   guid_list['tabdrag'] = true;                                   //   tabdrag-for-tablib
   guid_list['tabfx@chaosware.net'] = true;                       //   TabFX
   guid_list['tabsopenrelative@jomel.me.uk'] = true;              //   Tabs open ralative
   guid_list['tablib'] = true;                                    //   tablib
   guid_list['{328bbe91-cb86-40b0-a3fd-2b39969f9faa}'] = true;    //   Undo Close Tab
   guid_list['undoclosetab@dorando'] = true;                      //   Undo Close Tab
   guid_list['{99ec6690-8bb1-11da-a72b-0800200c9a66}'] = true;    //   Unread Tabs

   function prop(elm, str) {
      var arc = RDFService.GetResource("http://www.mozilla.org/2004/em-rdf#" + str);
      var target = extensionDS.GetTarget(elm, arc, true);
      if (target instanceof Components.interfaces.nsIRDFLiteral ||
              target instanceof Components.interfaces.nsIRDFInt)
         return target.Value;
      return null;
   }

   var RDFService = Components.classes["@mozilla.org/rdf/rdf-service;1"]
               .getService(Components.interfaces.nsIRDFService);
   var Container = Components.classes["@mozilla.org/rdf/container;1"]
               .getService(Components.interfaces.nsIRDFContainer);
   var extensionDS = Components.classes["@mozilla.org/extensions/manager;1"]
               .getService(Components.interfaces.nsIExtensionManager).datasource;

   var root = gIsOldBrowser ? "urn:mozilla:extension:" : "urn:mozilla:item:";
   var disabledString = gIsOldBrowser ? "disabled" : "userDisabled";

   try { // in ff 1.0.x we can get error at startup
      Container.Init(extensionDS, RDFService.GetResource(root + "root"));
   } catch (e) {
      tmLog("error in getExtensions " + e);
      return [];
   }

   var elements = Container.GetElements();
   var extensionsArray = [];

   while (elements.hasMoreElements()) {
      var element=elements.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
      var id = element.Value.replace(root, "");
      if (typeof guid_list[id.toLowerCase()] != "undefined") {
         var opType = prop(element, "opType");
         var disabled = prop(element, disabledString);
         if ((!disabled && opType != "needs-disable" && opType != "needs-uninstall") ||
             ( disabled && opType == "needs-enable")) {
            var name = prop(element, "name");
            name = name.charAt(0).toUpperCase() + name.substr(1);
            extensionsArray.push({_name: name, _guid: id, _version:prop(element, "version")});
         }
      }
   }
   return extensionsArray;
}
